"""
python p2_legal_solution_handwrite.py
"""

import json
import os
import copy
import random
import re
from bisect import bisect_left


# 读取仓库信息
def read_warehouse_data():
    with open('../fujian/fujian3/origin_data/warehouse.json') as f:
        return json.load(f)

# 读取品类平均库存量
def read_category_inventory():
    with open('../fujian/fujian3/data_from_p1/all_average_inventory.json') as f:
        return {d['category_id']: d['average_inventory'] for d in json.load(f)}

# 读取品类平均销量
def read_category_sales():
    with open('../fujian/fujian3/data_from_p1/all_average_sales.json') as f:
        return {d['category_id']: d['average_sales'] for d in json.load(f)}


warehouses = read_warehouse_data()
category_inventories = read_category_inventory()
category_sales = read_category_sales()
categories = []

# 按照最大库存量从大到小对仓库排序
# sorted_warehouses = sorted(warehouses, key=lambda x: x['max_inventory'], reverse=True)
# 按照最大库存量从小到大对仓库排序
sorted_warehouses = sorted(warehouses, key=lambda x: x['max_inventory'])


for warehouse in sorted_warehouses:
    match = re.search(r'\d+', warehouse['warehouse_id'])  # 提取数字
    if match:
        warehouse['warehouse_id'] = int(match.group())  # 转为整数类型
        
        # 修改 warehouse_id 为 id
for warehouse in sorted_warehouses:
    warehouse['id'] = warehouse.pop('warehouse_id')  # 使用 pop() 方法重命名键

# print(sorted_warehouses)
# quit()

for category_id in category_inventories:
    categories.append({
        'id': category_id,
        'inventory': category_inventories.get(category_id, 0),
        'sales': category_sales.get(category_id, 0)
    })
# sorted_categories = sorted(categories, key=lambda x: x['inventory'], reverse=True)
sorted_categories = sorted(categories, key=lambda x: x['inventory'])


for category in sorted_categories:
    category['id'] = int(category['id'])  # 将 id 转换为整数


# print(warehouses)
# print(categories) 

# print(sorted_categories)
print(sorted_warehouses)

# 定义检查函数
def check_numeric_values(data, array_name):
    for i, item in enumerate(data):
        for key, value in item.items():
            if not isinstance(value, (int, float)):
                raise TypeError(f"Error in {array_name}[{i}]['{key}']: Expected a numeric value, got {type(value).__name__}")

# 检查 sorted_categories 和 sorted_warehouses
check_numeric_values(sorted_categories, "sorted_categories")
check_numeric_values(sorted_warehouses, "sorted_warehouses")

# print("All values in sorted_categories and sorted_warehouses are numeric.")
print("这两个数组的所有值都是数字。")

# 定义检查函数
def check_categories(categories):
    for i, category in enumerate(categories):
        # 检查字段是否存在
        if not all(key in category for key in ['id', 'inventory', 'sales']):
            raise ValueError(f"Error in sorted_categories[{i}]: Missing one or more required fields.")
        
        # 检查字段值是否为数值类型
        for key in ['id', 'inventory', 'sales']:
            if not isinstance(category[key], (int, float)):
                raise TypeError(f"Error in sorted_categories[{i}]['{key}']: Expected a numeric value, got {type(category[key]).__name__}")

# 执行检查
check_categories(sorted_categories)
# print("All categories have the required fields and are numeric.")
print("sorted_category的所有value都是numeric类型")

    
# 定义检查函数
def check_warehouses(warehouses):
    for i, warehouse in enumerate(warehouses):
        # 检查字段是否存在
        if not all(key in warehouse for key in ['id', 'max_inventory', 'max_sales', 'daily_cost']):
            raise ValueError(f"Error in sorted_warehouses[{i}]: Missing one or more required fields.")
        
        # 检查字段值是否为数值类型
        for key in ['id', 'max_inventory', 'max_sales', 'daily_cost']:
            if not isinstance(warehouse[key], (int, float)):
                raise TypeError(f"Error in sorted_warehouses[{i}]['{key}']: Expected a numeric value, got {type(warehouse[key]).__name__}")

# 执行检查
check_warehouses(sorted_warehouses)
# print("All warehouses have the required fields and are numeric.")
print("sorted_warehouse的所有value都是numeric类型")

# M仓库 N品类
M = len(sorted_warehouses)
N = len(sorted_categories)
print("M = ", M)
print("N = ", N)

# print(sorted_warehouses[0]['max_inventory'])
# w0 = sorted_warehouses[0]
# w0['max_inventory'] -= 1
# print(sorted_warehouses[0]['max_inventory'])


print("展示一下格式")
print(sorted_categories[0])
print(sorted_warehouses[0])

ans = {}
# 键值对，key是cid，value是wid
# print("ans = ", ans)


chest_w = copy.deepcopy(sorted_warehouses)

# Mi仓库， Nj品类
for j in range(N):
    ans[j] = random.randint(0, 139)
    flag = False
    for i in range(M):
        wi = chest_w[i]
        cj = sorted_categories[j]
        
        if ( wi['max_inventory'] >= cj['inventory'] and wi['max_sales'] >= cj['sales']  ):
            wi['max_inventory'] -= cj['inventory']
            wi['max_sales'] -= cj['sales']
            # print(
            #     "仓库{}剩余的库存和出货量: {}, {} ".format(i, wi['max_inventory'], wi['max_sales'] )
            # )
            flag = True
            ans[j] = i
            # print( "ans[{}] = {}".format(i, j) )
            break
        
        # if i==M-1:
        #     raise RuntimeError("byd 你这么写就找不到可行解，换个写法")
    if ( flag==True ):
        print("find", end=" ")
    else :
        print("random", end=" ")
    
    print("ans[{}] = {}".format(j, ans[j]))

# print("ans = ", ans)

expected_keys = set(range(1, 351))
actual_keys = set(ans.keys())

if actual_keys == expected_keys:
    print("The dictionary contains keys from 1 to 350 (inclusive).")
else:
    print("The dictionary does not contain keys from 1 to 350 (inclusive).")

# print(sorted_warehouses)
# quit()

total_cost = 0
total_used_w_num = 0
bucket_w = [0] * M

for key, value in ans.items():
    # value范围是[0,M-1]
    # print(key, value)
    # print("品类{}的对应仓库是{}".format(key, value) )
    # print("idx ie value = {}", value)
    bucket_w[value] += 1
    

def get_w_obj(k):
    # print("in get_w_obj(): k={}".format(k))
    
    for i in range(M):
        obj = sorted_warehouses[i]
        # print("obj['id'] = {}, k = {}".format( obj['id'], k) )
        # print("obj['id'] == k", obj['id'] == k)
        if obj['id'] == (k+1):
            # print("obj that return: ", obj)
            return obj 
        
def get_c_obj(j):
    for j in range(N):
        obj = sorted_categories[j]
        if obj['id'] == j:
            return obj
    
    
for i in range(M):
    if ( bucket_w[i] > 0  ):
        total_used_w_num += 1
        total_cost += sorted_warehouses[i]['daily_cost']
        # total_cost += get_w_obj(i)['daily_cost']
        # print("now wobjidx={}, add={}".format(i,get_w_obj(i)['daily_cost']))
        # print("now total cost = {}".format(total_cost))
        
print("总共使用的仓库的数目: {}".format(total_used_w_num))
print("总日租成本: {}".format(total_cost))
# print("ans 字典（存储每一个品类对应哪一个仓库 = ", ans)

# ans_json_array = [{str(key): value} for key, value in ans.items()]
ans_json_array = [{str(sorted_categories[key]['id']): sorted_warehouses[value]['id']} for key, value in ans.items()]



# 定义输出目录和文件名
output_directory = '../fujian/p2/simple_solution_handwrite'
output_file_name = 'ans.json'
ans_json_array_output_path = os.path.join(output_directory, output_file_name)
# 创建目录（如果不存在）
os.makedirs(output_directory, exist_ok=True)
# 写入 JSON 文件
with open(ans_json_array_output_path, 'w') as f:
    json.dump(ans_json_array, f, indent=4)

print(f"ans 的字典写入到 {ans_json_array_output_path}")

        
# ans_utilization_inventory = [0] * M
# ans_utilization_sales = [0] * M

# def get_current_inventory(i):
#     """
#     i 是仓库编号， 返回这个仓库的当前库存
#     """
#     res = 0
#     for key, value in ans.items():
#     # print("品类{}的对应仓库是{}".format(key, value))
#         if ( value==i ):
#             res += get_c_obj(key)['inventory']
#     return res

# def get_current_sales(i):
#     """
#     i 是仓库编号， 返回这个仓库的当前出货量
#     """
#     res = 0
#     for key, value in ans.items():
#     # print("品类{}的对应仓库是{}".format(key, value))
#         if ( value==i ):
#             res += get_c_obj(key)['sales']    
#     return res
    

        
# for i in range(M):
#     obj = get_w_obj(i)
#     ans_utilization_inventory[i] = get_current_inventory(i) / obj['max_inventory']
#     ans_utilization_sales[i] = get_current_sales(i) / obj['max_sales']
    
# print(ans_utilization_inventory)
# print(ans_utilization_sales)
